/*
 * validaciones.c
 *
 *  Created on: 06/10/2013
 *      Author: AXL
 */

#include "validaciones.h"

typedef enum
{
	JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
} month_t;

/**
 * Valida que los argumentos pasados sean del tipo de dato indicado por formato.
 * PRE:		`datatypes` indica el tipo de dato a verificar.
 * RETURN 	0	todos los datos fueron validados y son correctos.
 *
 * EJ:
 * validateArgs(argc, argv, "cis" );
 * espera al menos 3 argumentos, el primero un char, el segundo un int y el
 * tercero un string.
 */
int validateArgs( int argc, char* argv[], const char* datatypes )
{
	char type;
	int readnum, i = 0;

	if ( argc != strlen( datatypes ) )/* argumentos de mas o de menos */
		return -1;

	while ( datatypes[i] != '\0' )
	{
		type = datatypes[i];

		switch ( type )
		{
			case 'c' :
				if ( strlen( argv[i] ) != 1 )
					return -1;
				break;

			case 'i' :
				sscanf( argv[i], "%*d%n", &readnum );
				if ( readnum == 0 )
					return -1;
				break;

			case 's' :
				/* es obvio que es char*, pero la opcion esta para mantener
				 * la logica del orden.
				 */
				break;
		}
		i++;
	}

	return 0;
}

/**
 * Verifica que (`min` <= `num` <=  `max`)
 * RETURN 	0	num esta fuera del rango.
 */
int inRange( int num, int min, int max )
{
	return num >= min && num <= max;
}

/**
 * Valida una fecha
 * RETURN 	0 	fecha invalida.
 */
int isDate( int day, int month )
{
	int max_day;

	if ( !inRange( month, 1, 12 ) )
		return 0;

	switch ( (month_t) month )
	{
		case FEB :
			max_day = 28; /* no me pagan lo suficiente como para checkear bisiesto :P */
			break;

		case JAN :
		case MAR :
		case MAY :
		case JUL :
		case AUG :
		case OCT :
		case DEC :
			max_day = 31;
			break;

		default :
			max_day = 30;
	}

	return inRange( day, 1, max_day );
}

/**
 * Valida que los numeros correspondan a una hora valida.
 * RETURN	0	validacion negativa
 */
int isTime( int hours, int minutes )
{
	if ( !inRange( hours, 0, 24 ) || !inRange( minutes, 0, 59 ) )
		return 0;

	return 1;
}

/**
 * Valida que la string recibida sea una fecha/hora de acuerdo al formato
 * establecido "yyyy-mm-dd hh:mm".
 * RETURN 	0	validacion negativa
 */
int isDateTimeString( char* date )
{
	int year, month, day, hour, mins, status;

	/*  leer un int para cada valor numerico y '-' o ':' como separadores */
	status = sscanf( date, "%d%*1[-]%d%*1[-]%d %d%*1[:]%d", &year, &month, &day,
			&hour, &mins );

	if ( status != 5 || !isDate( day, month ) || !isTime( hour, mins ) )
		return 0;

	return 1;
}
